package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {

    @Value("${ware.url}")
    private String wareUrl;

    @Resource
    private ProductFeignClient productFeignClient;

    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private OrderInfoMapper orderInfoMapper;

    @Resource
    private OrderDetailMapper orderDetailMapper;

    @Resource
    private CartInfoMapper cartInfoMapper;

    @Resource
    private RabbitService rabbitService;

    //保存订单
    @Override
    public Long submitOrder(OrderInfo orderInfo) {
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuilder stringBuilder = new StringBuilder();
        //总金额
        for (OrderDetail orderDetail : orderDetailList) {
            Long skuId = orderDetail.getSkuId();
            orderDetail.setOrderPrice(productFeignClient.getPrice(skuId));
            stringBuilder.append(orderDetail.getSkuName() + " ");
        }
        orderInfo.sumTotalAmount();
        //订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //订单交易编号
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单描述 所有商品的名称用空格隔开相加取前一百
        if (stringBuilder.toString().length() > 100){
            orderInfo.setTradeBody(stringBuilder.toString().substring(0,100));
        } else {
            orderInfo.setTradeBody(stringBuilder.toString());
        }
        //创建时间
        Calendar calendar = Calendar.getInstance();
        orderInfo.setCreateTime(calendar.getTime());
        //失效时间
        calendar.add(Calendar.MINUTE,30);
        orderInfo.setExpireTime(calendar.getTime());
        //进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //物流单编号
        //父订单编号
        //图片路径
        //保存订单详情
        orderInfoMapper.insert(orderInfo);
        //保存订单明细
        List<OrderDetail> orderDetails = orderInfo.getOrderDetailList();
        List<String> skuIds = new ArrayList<>();
        for (OrderDetail orderDetail : orderDetails) {
            orderDetail.setOrderId(orderInfo.getId());
            skuIds.add(orderDetail.getSkuId().toString());
            orderDetailMapper.insert(orderDetail);
        }
        //删除缓存中的已提交购物车
        Long userId = orderInfo.getUserId();
        String cacheCarInfo = RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cacheCarInfo, skuIds.toArray());
        //删除数据库中的已提交购物车
        CompletableFuture.runAsync(() -> {
            for (String skuId : skuIds) {
                cartInfoMapper.delete(new QueryWrapper<CartInfo>()
                        .eq("user_id",userId)
                        .eq("sku_id",Long.parseLong(skuId)));
            }
        });
        //订单超出支付时间 取消订单
        /*rabbitService.sendDeadLetterMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
                MqConst.ROUTING_ORDER_CANCEL1,
                orderInfo.getId(),7);*/
        return orderInfo.getId();
    }

    //校验库存
    @Override
    public Boolean hasStock(Long skuId, Integer skuNum) {
        String url = wareUrl + "/hasStock?skuId="+ skuId + "&num=" + skuNum;
        return HttpClientUtil.doGet(url).equals("0");
    }

    //取消订单
    @Override
    public void cancelOrder(Long orderInfoId) {

        OrderInfo orderInfo = orderInfoMapper.selectById(orderInfoId);
        if (orderInfo != null){
            //先查订单状态 判断是否还是未支付状态
            if (orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
                orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
                orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
                orderInfoMapper.updateById(orderInfo);
            }
        }
    }

    //根据Id查询订单
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new QueryWrapper<OrderDetail>()
                .eq("order_id", orderId));
        orderInfo.setOrderDetailList(orderDetailList);
        return orderInfo;
    }

    //更新订单状态
    @Override
    public void updateOrderStatus(Long orderInfoId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderInfoId);
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);
    }

    //发送消息 通知仓库
    @Override
    public void sendOrderStatus(Long orderInfoId) {
        //更新订单状态 为已通知仓库
        updateOrderStatus(orderInfoId,ProcessStatus.NOTIFIED_WARE);
        OrderInfo orderInfo = getOrderInfo(orderInfoId);
        //封装数据
        Map map = initWareOrder(orderInfo);
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,
                MqConst.ROUTING_WARE_STOCK, JSONObject.toJSON(map));
    }

    //封装发送给仓库所需的数据
    public Map initWareOrder(OrderInfo orderInfo) {
        Map<String,Object> map = new HashMap<>();
        map.put("orderId",orderInfo.getId());
        map.put("consignee",orderInfo.getConsignee());
        map.put("consigneeTel",orderInfo.getConsigneeTel());
        map.put("orderComment",orderInfo.getOrderComment());
        map.put("orderBody",orderInfo.getTradeBody());
        map.put("deliveryAddress",orderInfo.getDeliveryAddress());
        map.put("paymentWay","ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");
        // 仓库Id ，减库存拆单时需要使用！
        map.put("wareId", orderInfo.getWareId());
        List<Map<String, Object>> details = orderInfo.getOrderDetailList().stream().map(orderDetail -> {
            Map<String, Object> orderDetailMap = new HashMap<>();
            orderDetailMap.put("skuId", orderDetail.getSkuId());
            orderDetailMap.put("skuNum", orderDetail.getSkuNum());
            orderDetailMap.put("skuName", orderDetail.getSkuName());
            return orderDetailMap;
        }).collect(Collectors.toList());
        map.put("details",details);
        return map;
    }

    //拆单实现
    //参数1： 原订单的ID
    //参数2：   wareId ： 仓库ID    skuIds：此仓库中多个商品ID集合
    // [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
    @Override
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {
        OrderInfo orderInfoOrigin = getOrderInfo(orderId);
        //前提：转成ListMap
        List<Map> mapList = JSONObject.parseArray(wareSkuMap, Map.class);
        //子订单集合
        List<OrderInfo> subOrderInfoList = mapList.stream().map(map -> {
            //遍历仓库   每一个仓库就是map
            //一个仓库是一张订单
            //子订单  数据来原于父订单
            OrderInfo subOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(orderInfoOrigin,subOrderInfo);
            //解决问题：
            //1) 设置子订单的ID为null
            subOrderInfo.setId(null);
            //2) 设置父ID
            subOrderInfo.setParentOrderId(orderInfoOrigin.getId());
            //3)记录当前子订单是哪个仓库
            subOrderInfo.setWareId(String.valueOf(map.get("wareId")));
            //保存子订单的订单详情
            List<String> skuIds = (List<String>) map.get("skuIds");
            //一个仓库有多个子订单详情集合
            List<OrderDetail> subOrderDetailList = new ArrayList<>();
            for (String skuId : skuIds) {
                // 根据 skuId +  父Id
                //原始订单详情集合
                // Map 1 : {"wareId":"1","skuIds":["2","10"]}
                // Map 2 : {"wareId":"2","skuIds":["3"]}
                List<OrderDetail> orderDetailListOrigin = orderInfoOrigin.getOrderDetailList();
                for (OrderDetail orderDetailOrigin : orderDetailListOrigin) {
                    if(orderDetailOrigin.getSkuId().toString().equals(skuId)){
                        subOrderDetailList.add(orderDetailOrigin);
                        break;
                    }
                }
            }
            //3)设置子订单的订单详情的引用
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //计算总金额
            subOrderInfo.sumTotalAmount();
            //保存子订单
            orderInfoMapper.insert(subOrderInfo);

            //更新当前子订单对应的多个订单详情（设置外键）
            subOrderInfo.getOrderDetailList().forEach(orderDetail -> {
                orderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(orderDetail);
            });
            return subOrderInfo;
        }).collect(Collectors.toList());
        //更新原订单的订单状态 及进度状态
        updateOrderStatus(orderId,ProcessStatus.SPLIT);//实际 有所保留
        return subOrderInfoList;
    }

}
